home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 126-150 / disk_134 / dme / text2.c < prev   
C/C++ Source or Header  |  1992-05-06  |  22KB  |  1,109 lines

  1.  
  2. /*
  3.  * TEXT2.C
  4.  *
  5.  *    (C)Copyright 1987 by Matthew Dillon, All Rights Reserved
  6.  */
  7.  
  8. #include "defs.h"
  9. #include <stdio.h>
  10.  
  11. #define nomemory()  {memoryfail = 1;}
  12.  
  13. extern char MForceTitle;
  14. extern void do_bmove();
  15.  
  16. do_remeol()
  17. {
  18.     Current[Clen = Ep->Column] = 0;
  19.     text_sync();
  20.     text_redisplaycurrline();
  21. }
  22.  
  23. do_wleft()
  24. {
  25.     register ED *ep = Ep;
  26.     register ubyte *ptr;
  27.     register int i;
  28.  
  29.     for (;;) {
  30.     i = ep->Column;
  31.     if (i == 0)
  32.         goto prevline;
  33.     --i;
  34.     while (i && Current[i] == ' ')
  35.         --i;
  36.     if (i == 0 && Current[0] == ' ') {
  37. prevline:
  38.         if (Comlinemode || ep->Line == 0) {
  39.         i = ep->Column;
  40.         break;
  41.         }
  42.         text_sync();
  43.         --ep->Line;
  44.         text_load();
  45.         ep->Column = Clen;
  46.         continue;
  47.     }
  48.     while (i && Current[i] != ' ')
  49.         --i;
  50.     if (Current[i] == ' ')
  51.         ++i;
  52.     break;
  53.     }
  54.     ep->Column = i;
  55.     text_sync();
  56. }
  57.  
  58.  
  59. do_wright()
  60. {
  61.     register ubyte *ptr;
  62.     register ED *ep = Ep;
  63.     register int i;
  64.  
  65.     for (;;) {
  66.     i = ep->Column;
  67.     if (i == Clen)
  68.         goto nextline;
  69.     while (i != Clen && Current[i] != ' ')  /* skip past current word */
  70.         ++i;
  71.     while (i != Clen && Current[i] == ' ')  /* to beg. of next word   */
  72.         ++i;
  73.     if (i == Clen) {
  74. nextline:
  75.         if (Comlinemode || ep->Line == ep->Lines - 1) {
  76.         i = ep->Column;
  77.         break;
  78.         }
  79.         text_sync();
  80.         ++ep->Line;
  81.         text_load();
  82.         ep->Column = i = 0;
  83.         if (Current[0] != ' ')
  84.         break;
  85.         continue;
  86.     }
  87.     break;
  88.     }
  89.     ep->Column = i;
  90.     text_sync();
  91. }
  92.  
  93.  
  94. do_split()              /* split line in two at cursor pos */
  95. {
  96.     ubyte buf[256];
  97.     register ED *ep = Ep;
  98.  
  99.     strcpy(buf, Current+ep->Column);
  100.     Current[Clen = ep->Column] = '\0';
  101.     text_sync();
  102.     SetAPen(Rp, 0);
  103.     if (Nsu == 0)
  104.     RectFill(Rp, COL(0), ROW(ep->Line-ep->Topline), Xbase+Xpixs, ROW(ep->Line-ep->Topline+1)-1);
  105.     SetAPen(Rp, 1);
  106.     text_displayseg(ep->Line - ep->Topline, 1);
  107.     do_downadd();
  108.     do_insline();
  109.     strcpy(Current, buf);
  110.     Clen = strlen(Current);
  111.     text_sync();
  112.     text_displayseg(ep->Line - ep->Topline, 1);
  113.     do_up();
  114. }
  115.  
  116. do_join()
  117. {
  118.     register int i = Clen, j;
  119.     register ED *ep = Ep;
  120.  
  121.     if (ep->Line + 1 < ep->Lines && strlen(ep->List[ep->Line+1])+i <= 253) {
  122.     if (i && Current[i-1] != ' ')
  123.         Current[i++] = ' ';
  124.     strcpy(Current+i, ep->List[ep->Line+1]);
  125.     for (j = i; Current[j] == ' '; ++j);
  126.     for (; i >= 0 && Current[i] == ' '; --i);
  127.     if (j > i+2)
  128.         bmov(Current+j, Current+i+2, strlen(Current+j)+1);
  129.     Clen = strlen(Current);
  130.     text_sync();
  131.     text_displayseg(ep->Line - ep->Topline, 1);
  132.     do_down();
  133.     do_deline();
  134.     do_up();
  135.     return(1);
  136.     }
  137.     return(0);
  138. }
  139.  
  140. do_margin()
  141. {
  142.     Ep->Margin = atoi(av[1]);
  143. }
  144.  
  145. do_wordwrap()
  146. {
  147.     register ED *ep = Ep;
  148.  
  149.     if (av[1][1] == 'n')
  150.     ep->Wordwrap = 1;
  151.     if (av[1][1] == 'f')
  152.     ep->Wordwrap = 0;
  153.     if (av[1][0] == 't')
  154.     ep->Wordwrap = 1 - ep->Wordwrap;
  155.     if (ep->Wordwrap)
  156.     title("Wordwrap ON");
  157.     else
  158.     title("Wordwrap OFF");
  159. }
  160.  
  161. /*
  162.  * n == -1  :    force reformat entire paragraph
  163.  * n ==  0  :    only until line equalizes (from text_write())
  164.  *
  165.  * What is a paragraph?   A paragraph ends whenever the left justification
  166.  * gets larger, or on a blank line.
  167.  */
  168.  
  169. do_reformat(n)
  170. {
  171.     register char *str;
  172.     register ED *ep = Ep;
  173.     int nlok, lnsc, fnst, fnsc;
  174.     int column = ep->Column;
  175.     int srow   = ep->Line;
  176.     int crow   = srow;
  177.     int erow   = srow;
  178.     short dins = 0;        /* relative insert lines/delete lines   */
  179.     char moded = 0;        /* any modifications done at all?        */
  180.     char checked = 0;        /* for cursor positioning.            */
  181.  
  182.     if (ep->Margin == 0)
  183.     ep->Margin = 75;
  184.  
  185.     ++Nsu;
  186.     for (;;) {
  187.     str = (char *)ep->List[ep->Line+1];
  188.     fnst = 0;
  189.     fnsc = firstns(Current);
  190.     nlok = (ep->Line + 1 < ep->Lines && fnsc >= (fnst=firstns(str)));
  191.     if (nlok && str[0] == 0)
  192.         nlok = 0;
  193.     lnsc = lastns(Current);
  194.     if (lnsc < ep->Margin) {    /* space at end of line for marg-lnsc-2 letter word   */
  195.         if (nlok == 0)        /* but no more data to joinup   */
  196.         break;          /* done */
  197.         if (ep->Margin - lnsc - 2 >= wordlen(str+fnst)) {
  198.         ep->Column = 0;
  199.         Clen = lastns(Current);
  200.         if (Current[Clen])
  201.             ++Clen;
  202.         moded = 1;
  203.         --dins;
  204.         if (do_join())
  205.             continue;
  206.         ++dins;
  207.         title("Error, Margin > 124");
  208.         break;
  209.         }
  210.         if (n == 0)        /* if couldn't mod line, and text_write, don't update any more */
  211.         break;
  212.         do_down();
  213.         erow = ep->Line;
  214.         continue;
  215.     }
  216.                 /* no space, need to split    */
  217.                 /* find start of prev word    */
  218.     for (;;) {
  219.         register int i = lnsc;
  220.         while (i && Current[i] != ' ')
  221.         --i;
  222.         lnsc = i;
  223.         if (i >= ep->Margin) {
  224.         while (i && Current[i] == ' ')
  225.             --i;
  226.         if (i < ep->Margin)
  227.             break;
  228.         lnsc = i;
  229.         continue;
  230.         }
  231.         break;
  232.     }
  233.     if (lnsc) {             /* ok to split at word          */
  234.         ++lnsc;
  235.         ++dins;
  236.         ep->Column = lnsc;
  237.         do_split(); /* Split at point LNSC          */
  238.         do_down();          /* must insert proper amount?   */
  239.         {
  240.         int indent = (nlok == 0) ? fnsc : fnst;
  241.         if (!checked) {
  242.             checked = 1;
  243.             if (lnsc <= column) {   /* if split before cursor   */
  244.             column = column - ep->Column + indent;
  245.             ++crow;
  246.             }
  247.         }
  248.         if (Clen + indent < 253) {
  249.             bmov(Current, Current + indent, strlen(Current)+1);
  250.             bset(Current, indent, ' ');
  251.             Clen += indent;
  252.         }
  253.         }
  254.         erow = ep->Line;
  255.         continue;
  256.     }
  257.     if (n == 0)
  258.         break;
  259.     do_down();
  260.     }
  261.     if (column < 0 || column > 200)
  262.     column = 0;
  263.     if (srow >= ep->Lines) {
  264.     srow = ep->Lines - 1;
  265.     goto ra;
  266.     }
  267.     if (dins || srow < ep->Topline || srow >= ep->Topline + Rows) {
  268. ra:
  269.     text_sync();
  270.     --Nsu;
  271.     ep->Line = crow;
  272.     ep->Column = column;
  273.     text_load();
  274.     if (!text_sync())
  275.         text_redisplay();
  276.     } else {
  277.     text_sync();
  278.     --Nsu;
  279.     ep->Line = crow;
  280.     ep->Column = column;
  281.     text_load();
  282.     if (erow != srow) {
  283.         if (!text_sync()) {
  284.         ++erow;
  285.         if (erow - ep->Topline > Rows)
  286.             erow = ep->Topline + Rows;
  287.         SetAPen(Rp, 0);
  288.         RectFill(Rp, COL(0), ROW(srow - ep->Topline), Xbase+Xpixs, ROW(erow - ep->Topline)-1);
  289.         SetAPen(Rp, 1);
  290.         text_displayseg(srow - ep->Topline, erow - srow);
  291.         }
  292.     } else {
  293.         text_sync();
  294.         if (moded)
  295.         text_redisplaycurrline();
  296.     }
  297.     }
  298.     if (column > Clen) {
  299.     bset(Current+Clen, column - Clen, ' ');
  300.     Current[column] = 0;
  301.     }
  302.     ep->Column = column;
  303. }
  304.  
  305.  
  306. do_tabstop()
  307. {
  308.     Ep->Tabstop = atoi(av[1]);
  309. }
  310.  
  311.  
  312. do_insertmode()
  313. {
  314.     register ED *ep = Ep;
  315.  
  316.     if (av[1][0]) {
  317.     switch(av[1][1] & 0x1F) {
  318.     case 'n'&0x1F:
  319.         ep->Insertmode = 1;
  320.         break;
  321.     case 'f'&0x1F:
  322.         ep->Insertmode = 0;
  323.         break;
  324.     case 'o'&0x1F:
  325.         ep->Insertmode = 1 - ep->Insertmode;
  326.         break;
  327.     }
  328.     if (ep->Insertmode)
  329.         title("Insert mode on");
  330.     else
  331.         title("Insert mode off");
  332.     }
  333. }
  334.  
  335. do_insline()
  336. {
  337.     register ubyte *ptr;
  338.     register ED *ep = Ep;
  339.  
  340.     ep->Modified = 1;
  341.     text_sync();
  342.     if (makeroom(32) && (ptr = allocb(1))) {
  343.     bmovl(ep->List+ep->Line, ep->List+ep->Line+1,ep->Lines-ep->Line);
  344.     ep->List[ep->Line] = ptr;
  345.     *ptr = 0;
  346.     ++ep->Lines;
  347.     if (BEp == ep) {
  348.         if (ep->Line < BSline)
  349.         ++BSline;
  350.         if (ep->Line <= BEline)
  351.         ++BEline;
  352.     }
  353.     } else {
  354.     nomemory();
  355.     }
  356.     text_load();
  357.     if (Nsu == 0)
  358.     ScrollRaster(Rp,0,-Ysize, COL(0), ROW(ep->Line-ep->Topline), COL(Columns)-1, ROW(Rows)-1);
  359.     text_displayseg(ep->Line - ep->Topline, 1);
  360. }
  361.  
  362. do_deline()
  363. {
  364.     register int delline;
  365.     register ED *ep = Ep;
  366.  
  367.     if (ep->Lines > 1) {
  368.     ep->Modified = 1;
  369.     text_sync();
  370.  
  371.     FreeMem(ep->List[ep->Line], strlen(ep->List[ep->Line])+1);
  372.     bmovl(ep->List+ep->Line+1, ep->List+ep->Line,ep->Lines-ep->Line-1);
  373.     if (BEp == ep) {
  374.         if (ep->Line < BSline)
  375.         --BSline;
  376.         if (ep->Line <= BEline)
  377.         --BEline;
  378.     }
  379.     delline = ep->Line;
  380.     if (ep->Line >= --ep->Lines) {
  381.         --ep->Line;
  382.         text_load();
  383.         if (ep->Line < ep->Topline) {
  384.         if (Nsu == 0) {
  385.             ep->Topline = ep->Line - (Rows>>1);
  386.             if (ep->Topline < 0)
  387.             ep->Topline = 0;
  388.             text_redisplay();
  389.         }
  390.         return(0);
  391.         }
  392.     }
  393.     text_load();
  394.     if (Nsu == 0)
  395.         ScrollRaster(Rp,0,Ysize, COL(0), ROW(delline-ep->Topline), COL(Columns)-1, ROW(Rows)-1);
  396.     text_displayseg(Rows-1, 1);
  397.     } else {
  398.     do_firstcolumn();
  399.     do_remeol();
  400.     ep->Modified = 0;
  401.     }
  402. }
  403.  
  404. do_chfilename()
  405. {
  406.     text_sync();
  407.     strncpy(Ep->Name, av[1], 63);
  408.     MForceTitle = 1;
  409. }
  410.  
  411. do_edit()
  412. {
  413.     long xfi;
  414.     long oldlock;
  415.     long lines;
  416.     ubyte buf[256];
  417.     ubyte *ptr;
  418.     char failed = 1;
  419.     short iwinx, iwiny;
  420.     char  tabstop, margin, insertmode, wordwrap;
  421.     register ED *ep = Ep;
  422.  
  423.     text_sync();
  424.     if (*av[0] == 'n') {        /* newfile or insfile   */
  425.     if (ep->Modified && getyn("Delete modified Image?") == 0)
  426.         return(0);
  427.     iwinx = ep->IWinx;
  428.     iwiny = ep->IWiny;
  429.     tabstop= ep->Tabstop;
  430.     margin = ep->Margin;
  431.     insertmode = ep->Insertmode;
  432.     wordwrap = ep->Wordwrap;
  433.     text_uninit();
  434.     text_init();
  435.     ep = Ep;
  436.     ep->IWiny = iwiny;
  437.     ep->IWinx = iwinx;
  438.     ep->Tabstop = tabstop;
  439.     ep->Margin  = margin;
  440.     ep->Insertmode = insertmode;
  441.     ep->Wordwrap = wordwrap;
  442.     ep->Modified = 0;
  443.     ep->Line = ep->Topline = 0;
  444.     strncpy(ep->Name, av[1], 63);
  445.     } else {
  446.     ep->Modified = 1;
  447.     }
  448.     lines = ep->Lines;
  449.     if (Wbs && Wdisable == 0)
  450.     oldlock = CurrentDir(ep->dirlock);
  451.     if (xfi = xfopen(av[1], "r", 4096)) {
  452.     register int len;
  453.     char oktitle = 1;
  454.  
  455.     title("Loading...");
  456.     while ((len = xefgets(xfi, buf, 255)) >= 0) {
  457.         failed = 0;
  458.         if (makeroom(256) && (ptr = allocb(len+1))) {
  459.         ep->List[ep->Lines++] = ptr;
  460.         bmov(buf, ptr, len+1);
  461.         } else {
  462.         set_window_params();
  463.         nomemory();
  464.         oktitle = 0;
  465.         break;
  466.         }
  467.     }
  468.     set_window_params();
  469.     if (oktitle)
  470.         title("OK");
  471.     } else {
  472.     title("File Not Found");
  473.     }
  474.     xfclose(xfi);
  475.     if (Wbs && Wdisable == 0)
  476.     CurrentDir(oldlock);
  477.     if (ep->Lines != 1 && lines == 1 && ep->List[0][0] == 0) {
  478.     ep->Modified = 0;
  479.     ep->Line = 0;
  480.     FreeMem(ep->List[0], strlen(ep->List[0])+1);
  481.     bmovl(ep->List+1, ep->List,--ep->Lines);
  482.     } else {
  483.     if (!failed && lines <= ep->Lines - 1) {
  484.         BEp = ep;
  485.         BSline = lines;
  486.         BEline = ep->Lines - 1;
  487.         do_bmove();
  488.     }
  489.     }
  490.     set_window_params();
  491.     text_load();
  492.     text_redisplay();
  493. }
  494.  
  495. static char blockmode;
  496.  
  497. do_bsave()
  498. {
  499.     blockmode = 1;
  500.     do_saveas();
  501. }
  502.  
  503. do_save()
  504. {
  505.     av[1] = Ep->Name;
  506.     do_saveas();
  507. }
  508.  
  509. do_savetabs()
  510. {
  511.     Savetabs = (av[1][0] && av[1][1] == 'n') ? 1 : 0;
  512. }
  513.  
  514. do_saveas()
  515. {
  516.     long oldlock;
  517.     long xfi;
  518.     register long i;
  519.     register short j, k;
  520.     register ubyte *ptr, *bp;
  521.     long xs, xe;
  522.     ubyte buf[256];
  523.     char bm;
  524.     ED *ep;
  525.  
  526.     bm = blockmode;
  527.     if (blockmode && blockok()) {
  528.     xs = BSline;
  529.     xe = BEline + 1;
  530.     ep = BEp;
  531.     } else {
  532.     xs = 0;
  533.     xe = Ep->Lines;
  534.     ep = Ep;
  535.     }
  536.     blockmode = 0;
  537.     text_sync();
  538.     if (Wbs && Wdisable == 0) {     /* Write out .info file */
  539.     DISKOBJ sdo, *d;
  540.     bzero(&sdo, sizeof(sdo));
  541.     oldlock = CurrentDir(Ep->dirlock);
  542.     if ((d = GetDiskObject(av[1])) == NULL) {
  543.         if (getpath(Wbs->sm_ArgList[0].wa_Name, buf)) {
  544.         sdo.do_Magic = WB_DISKMAGIC;
  545.         sdo.do_Version = WB_DISKVERSION;
  546.         makemygadget(&sdo.do_Gadget);
  547.         sdo.do_Type = WBPROJECT;
  548.         sdo.do_DefaultTool = (char *)buf;
  549.         sdo.do_ToolTypes = NULL;
  550.         sdo.do_CurrentX = NO_ICON_POSITION;
  551.         sdo.do_CurrentY = NO_ICON_POSITION;
  552.         sdo.do_DrawerData = NULL;
  553.         sdo.do_ToolWindow = NULL;
  554.         sdo.do_StackSize = 8192;
  555.         PutDiskObject(av[1], &sdo);
  556.         }
  557.     } else {
  558.         FreeDiskObject(d);
  559.     }
  560.     }
  561.     if (xfi = xfopen(av[1], "w", 4096)) {
  562.     title("Saving...");
  563.     for (i = xs; i < xe; ++i) {
  564.         ptr = ep->List[i];
  565.         if (Savetabs) {
  566.         for (bp = buf, j = 0; *ptr; ++ptr, ++bp, j = (j+1)&7) {
  567.             *bp = *ptr;
  568.             if (j == 7 && *bp == ' ' && *(bp-1) == ' ') {
  569.             k = j;
  570.             while (k-- >= 0 && *bp == ' ')
  571.                 --bp;
  572.             *++bp = 9;
  573.             } else {
  574.             if (*bp == '\"' || *bp == '\'' || *bp == '\`' || *bp == '(')
  575.                 break;
  576.             }
  577.         }
  578.         strcpy(bp, ptr);
  579.         ptr = buf;
  580.         }
  581.         xfwrite(xfi, ptr, strlen(ptr));
  582.         if (xfwrite(xfi, "\n", 1)) {
  583.         xfclose(xfi);
  584.         goto err;
  585.         }
  586.     }
  587.     if (xfclose(xfi)) {
  588. err:        Abortcommand = 1;
  589.         title("WRITE FAILED!");
  590.     } else {
  591.         ep->Modified &= bm;
  592.         title("OK");
  593.     }
  594.     if (Wbs && Wdisable == 0)
  595.         CurrentDir(oldlock);
  596.     } else {
  597.     title("Unable to open write file");
  598.     Abortcommand = 1;
  599.     }
  600. }
  601.  
  602.  
  603. do_block()          /* block, unblock   */
  604. {
  605.     text_sync();
  606.     switch(av[0][0]) {
  607.     case 'b':
  608.     if (BSline < 0) {
  609.         BSline = Ep->Line;
  610.         title("Block Begin");
  611.     } else {
  612.         if (BEp) {
  613.         title("Block Already Marked");
  614.         break;
  615.         }
  616.         title("Block End");
  617.         BEline = Ep->Line;
  618.         if (BSline > BEline) {
  619.         BEline = BSline;
  620.         BSline = Ep->Line;
  621.         }
  622.         BEp = Ep;
  623.         text_redrawblock(1);
  624.     }
  625.     break;
  626.     case 'u':
  627.     text_redrawblock(0);
  628.     title ("Block Unmarked");
  629.     break;
  630.     }
  631. }
  632.  
  633. static
  634. blockok()
  635. {
  636.     if (BEp && BSline >= 0 && BSline <= BEline && BEline < BEp->Lines)
  637.     return(1);
  638.     BEp = NULL;
  639.     BSline = BEline = -1;
  640.     title("Block Not Specified");
  641.     return(0);
  642. }
  643.  
  644.  
  645. do_bdelete()
  646. {
  647.     register long i, n;
  648.     register ED *bep = BEp;
  649.     register WIN *savewin = Ep->Win;
  650.  
  651.     if (blockok()) {
  652.     text_switch(bep->Win);
  653.     n = BEline - BSline + 1;
  654.     if (bep->Line >= BSline && bep->Line <= BEline)
  655.         bep->Line = BSline;
  656.     if (bep->Line > BEline)
  657.         bep->Line -= n;
  658.     freelist(bep->List + BSline, BEline - BSline + 1);
  659.     bmovl(bep->List+BEline+1,bep->List+BSline,(bep->Lines-BEline-1));
  660.     bep->Lines -= n;
  661.     bep->Modified = 1;
  662.     if (bep->Line >= bep->Lines)
  663.         bep->Line = bep->Lines - 1;
  664.     if (bep->Line < 0)
  665.         bep->Line = 0;
  666.     if (bep->Lines == 0) {
  667.         text_uninit();
  668.         text_init();
  669.     }
  670.     text_load();
  671.     BEp = NULL;
  672.     BSline = BEline = -1;
  673.     if (!text_sync())
  674.         text_redisplay();
  675.     text_switch(savewin);
  676.     }
  677. }
  678.  
  679. void
  680. do_bcopy()
  681. {
  682.     register ubyte **list;
  683.     register long lines, i;
  684.     register ED *ep = Ep;
  685.  
  686.     text_sync();
  687.     if (!blockok())
  688.     return;
  689.     if (ep == BEp && ep->Line > BSline && ep->Line <= BEline) {
  690.     title("Cannot Move into self");
  691.     return;
  692.     }
  693.     lines = BEline - BSline + 1;
  694.     if (extend(ep, lines)) {
  695.     if (list = (ubyte **)allocl(lines)) {
  696.         bmovl(BEp->List+BSline,list,lines);
  697.         bmovl(ep->List+ep->Line, ep->List+ep->Line+lines, ep->Lines-ep->Line);
  698.         for (i = 0; i < lines; ++i) {
  699.         ubyte *str = allocb(strlen(list[i])+1);
  700.         if (!str) {
  701.             nomemory();
  702.             FreeMem(list, lines * sizeof(char *));
  703.             freelist(ep->List + Ep->Line, i);
  704.             bmovl(ep->List+ep->Line+lines, ep->List+ep->Line, ep->Lines-ep->Line);
  705.             return;
  706.         }
  707.         strcpy(str, list[i]);
  708.         ep->List[ep->Line+i] = str;
  709.         }
  710.         FreeMem(list, lines * sizeof(char *));
  711.     }
  712.     }
  713.     if (ep == BEp && ep->Line <= BSline) {
  714.     BSline += lines;
  715.     BEline += lines;
  716.     }
  717.     ep->Modified = 1;
  718.     ep->Lines += lines;
  719.     text_load();
  720.     if (!text_sync())
  721.     text_redisplay();
  722. }
  723.  
  724.  
  725. void
  726. do_bmove()
  727. {
  728.     register long lines;
  729.     register ubyte **list;
  730.     register ED *ep = Ep;
  731.  
  732.     text_sync();
  733.     if (!blockok())
  734.     return;
  735.     if (BEp == ep && ep->Line >= BSline && ep->Line <= BEline) {
  736.     title("Cannot Move into self");
  737.     return;
  738.     }
  739.     lines = BEline - BSline + 1;
  740.     if (!(list = (ubyte **)allocl(lines))) {
  741.     nomemory();
  742.     return;
  743.     }
  744.     bmovl(BEp->List + BSline, list, lines);
  745.     if (ep == BEp) {
  746.     if (ep->Line > BSline) {
  747.         bmovl(ep->List+BEline+1, ep->List+BSline, ep->Line-BEline-1);
  748.         bmovl(list, ep->List + ep->Line - lines, lines);
  749.     } else {
  750.         bmovl(ep->List+ep->Line, ep->List+ep->Line+lines, BSline-ep->Line);
  751.         bmovl(list, ep->List + ep->Line, lines);
  752.     }
  753.     } else {
  754.     WIN *savewin = ep->Win;
  755.     if (extend(ep, lines)) {
  756.         bmovl(BEp->List+BEline+1, BEp->List+BSline, BEp->Lines-BEline-1);
  757.         bmovl(ep->List+ep->Line, ep->List+ep->Line+lines, ep->Lines-ep->Line);
  758.         bmovl(list, ep->List+ep->Line, lines);
  759.         ep->Lines += lines;
  760.         BEp->Lines -= lines;
  761.         if (BEp->Line >= BSline && BEp->Line <= BEline)
  762.         BEp->Line = BSline - 1;
  763.         if (BEp->Line > BEline)
  764.         BEp->Line -= lines;
  765.         if (BEp->Line < 0)
  766.         BEp->Line = 0;
  767.         BSline = BEline = -1;
  768.         text_load();
  769.         text_switch(BEp->Win);
  770.         BEp = NULL;
  771.         ep = Ep;
  772.         if (!ep->iconmode) {
  773.         if (!text_sync())
  774.             text_redisplay();
  775.         }
  776.         text_switch(savewin);
  777.         ep = Ep;
  778.     }
  779.     }
  780.     BSline = BEline = -1;
  781.     BEp = NULL;
  782.     FreeMem(list, lines * sizeof(char *));
  783.     BEp->Modified = 1;
  784.     ep->Modified = 1;
  785.     text_load();
  786.     if (!text_sync())
  787.     text_redisplay();
  788. }
  789.  
  790.  
  791. /*
  792.  * IF condition trueaction, IFELSE condition trueaction falseaction
  793.  *
  794.  *  condition:    !condition NOT the specified condition.
  795.  *        #       toggle number is SET
  796.  *        top       top of file (on first line)
  797.  *        bot       end of file (on last line)
  798.  *        left       start of line (leftmost column)
  799.  *        right       end of line (nothing but spaces under and to the right)
  800.  *        modified   text has been modified
  801.  *        insert       currently in insert mode
  802.  *        y[<=>]#    cursor is (any OR combo of <,>,=) row #  (line numbers start at 1)
  803.  *        x[<=>]#    cursor is (<,>,<=,>=,<>) column #        (columns start at 1)
  804.  *                <> means 'not equal'
  805.  *
  806.  *        cl       char under cursor is lower case
  807.  *        cu       char under cursor is upper case
  808.  *        ca       char under cursor is alpha
  809.  *        cn       char under cursor is numeric
  810.  *        cb       char within selected block
  811.  *        c[<=>]#    char under cursor is (combo of <,>,and =) #
  812.  */
  813.  
  814. do_if()
  815. {
  816.     char haselse = (av[0][2] == 'e');
  817.     char iswhile = (av[0][0] == 'w');
  818.     char istrue, notop = 0;
  819.     char c, cx, cc;
  820.     ubyte *buf1, *buf2;
  821.     register ubyte *ptr;
  822.     register ED *ep = Ep;
  823.     int i, cxn, cn;
  824.  
  825.     buf1 = (ubyte *)malloc(256);
  826.     buf2 = (ubyte *)malloc(256);
  827.     if (buf1 == NULL || buf2 == NULL) {
  828.     if (buf1) free(buf1);
  829.     if (buf2) free(buf2);
  830.     title("No Memory!");
  831.     return(0);
  832.     }
  833.     breakreset();
  834.     ptr = av[1];
  835.     if (*ptr == '!') {
  836.     notop = 1;
  837.     ++ptr;
  838.     }
  839.     c = ptr[0];
  840.     cn= atoi(ptr);
  841.     cx= ptr[1];
  842.     cxn=atoi(ptr+1);
  843.     strcpy(buf1, av[2]);
  844.  
  845. loop:
  846.     istrue = 0;
  847.     i = 0;
  848.     switch(c) {
  849.     case 'x':
  850.     i = ep->Column + 1;
  851.     case 'y':
  852.     if (!i)
  853.         i = ep->Line + 1;
  854. conditional:
  855.     {
  856.         register int j, n;
  857.         char any = 0;
  858.  
  859.         for (j = 1; ptr[j] && (ptr[j]<'0'||ptr[j]>'9'); ++j);
  860.         n = atoi(ptr+j);
  861.         for (j = 1; ptr[j]; ++j) {
  862.         switch(ptr[j]) {
  863.         case '<':
  864.             any = 1;
  865.             if (i < n)
  866.             istrue = 1;
  867.             break;
  868.         case '=':
  869.             any = 1;
  870.             if (i == n)
  871.             istrue = 1;
  872.             break;
  873.         case '>':
  874.             any = 1;
  875.             if (i > n)
  876.             istrue = 1;
  877.             break;
  878.         }
  879.         }
  880.         if (!any && i == n)  /* default is equivalence   */
  881.         istrue = 1;
  882.     }
  883.     break;
  884.     case 't':
  885.     istrue = ep->Line == 0;
  886.     break;
  887.     case 'b':
  888.     istrue = ep->Line == ep->Lines-1;
  889.     break;
  890.     case 'l':
  891.     istrue = ep->Column == 0;
  892.     break;
  893.     case 'r':
  894.     istrue = ep->Column == Clen;
  895.     break;
  896.     case 'm':
  897.     text_sync();
  898.     istrue = ep->Modified != 0;
  899.     break;
  900.     case 'i':
  901.     istrue = ep->Insertmode != 0;
  902.     break;
  903.     case 'c':
  904.     cc = Current[ep->Column];
  905.     switch(cx) {
  906.     case 'b':
  907.         istrue = BEp == ep && ep->Line >= BSline && ep->Line <= BEline;
  908.         break;
  909.     case 'l':
  910.         istrue = cc >= 'a' && cc <= 'z';
  911.         break;
  912.     case 'u':
  913.         istrue = cc >= 'A' && cc <= 'Z';
  914.         break;
  915.     case 'a':
  916.         istrue = (cc>='a'&&cc<='z')||(cc>='A'&&cc<='Z')||(cc>='0'&&cc<='9');
  917.         break;
  918.     case 'n':
  919.         istrue = (cc >= '0' && cc <= '9');
  920.         break;
  921.     default:        /* c[<=>]#  */
  922.         i = Current[ep->Column];
  923.         goto conditional;
  924.         break;
  925.     }
  926.     break;
  927.     default:
  928.     if (c >= '0' && c <= '9')
  929.         istrue = do_toggle(cn) != 0;
  930.     else
  931.         title("bad conditional");
  932.     break;
  933.     }
  934.     istrue ^= notop;
  935.     if (istrue) {
  936.     strcpy(buf2, buf1);     /* could be executed multiple times */
  937.     if (do_command(buf2) == 0)
  938.         goto done;
  939.     if (iswhile) {
  940.         if (breakcheck())
  941.         Abortcommand = 1;
  942.         else
  943.         goto loop;
  944.     }
  945.     } else {
  946.     if (haselse) {          /* only executed once */
  947.         strcpy(buf2, av[3]);
  948.         do_command(buf2);
  949.     }
  950.     }
  951. done:
  952.     free(buf1);
  953.     free(buf2);
  954. }
  955.  
  956.  
  957. /*
  958.  * TOGGLE #, SETTOGGLE #, RESETTOGGLE #
  959.  */
  960.  
  961. do_toggle(n)
  962. {
  963.     static char tg[MAXTOGGLE];
  964.     register int i;
  965.  
  966.     if (n >= 0) {
  967.     if (n >= MAXTOGGLE)
  968.         return(0);
  969.     return(tg[n]);
  970.     }
  971.     i = atoi(av[1]);
  972.     if (i >= 0 && i < MAXTOGGLE) {
  973.     switch(av[0][0]) {
  974.     case 't':
  975.         tg[i] = !tg[i];
  976.         break;
  977.     case 's':
  978.         tg[i] = 1;
  979.         break;
  980.     case 'r':
  981.         tg[i] = 0;
  982.         break;
  983.     }
  984.     }
  985. }
  986.  
  987.  
  988. do_tlate()
  989. {
  990.     register ubyte *ptr = av[1];
  991.     register ED *ep = Ep;
  992.     register char c = Current[ep->Column];
  993.  
  994.     if (c == 0)
  995.     c = ' ';
  996.     if (ptr[0] == '+')
  997.     c += atoi(ptr+1);
  998.     else
  999.     if (ptr[0] == '-')
  1000.     c -= atoi(ptr+1);
  1001.     else
  1002.     c = atoi(ptr);
  1003.     if (c) {
  1004.     if (Current[ep->Column] == 0) {
  1005.         Clen = ep->Column + 1;
  1006.         Current[Clen] = 0;
  1007.     }
  1008.     Current[ep->Column] = c;
  1009.     if (Nsu == 0) {
  1010.         movetocursor();
  1011.         setpen(ep->Line);
  1012.         Text(Rp, Current+ep->Column, 1);
  1013.     }
  1014.     }
  1015. }
  1016.  
  1017. /*
  1018.  *  BSOURCE
  1019.  *
  1020.  *  note that since the start and end lines are loaded immediately and the
  1021.  *  block unblock'd before execution starts, you can theoretically have
  1022.  *  another BSOURCE as part of this BSOURCE (but be carefull!).
  1023.  */
  1024.  
  1025. do_bsource()
  1026. {
  1027.     ubyte buf[256];
  1028.     register int i, sl, se;
  1029.  
  1030.     if (blockok()) {
  1031.     sl = BSline;
  1032.     se = BEline + 1;
  1033.     for (i = sl; BEp && i < se && i < BEp->Lines; ++i) {
  1034.         text_sync();        /* make sure we are using latest text */
  1035.         strcpy(buf, BEp->List[i]);
  1036.         if (do_command(buf) == 0)
  1037.         break;
  1038.     }
  1039.     text_redrawblock(0);
  1040.     }
  1041. }
  1042.  
  1043. /*
  1044.  *  SCANF controlstring
  1045.  *
  1046.  *  The C scanf routine.  Only one variable, a string, is allowed in the
  1047.  *  control string.
  1048.  */
  1049.  
  1050. void
  1051. do_scanf()
  1052. {
  1053.     char buf[256];
  1054.  
  1055.     buf[0] = 0;
  1056.     sscanf(Current+Ep->Column,av[1],buf,buf,buf,buf,buf,buf,buf);
  1057.     if (String)
  1058.     free(String);
  1059.     String = (char *)malloc(strlen(buf)+1);
  1060.     strcpy(String,buf);
  1061.     title(String);
  1062. }
  1063.  
  1064. movetocursor()
  1065. {
  1066.     register ED *ep = Ep;
  1067.     Move(Rp, XTbase+(ep->Column-ep->Topcolumn)*Xsize, YTbase+(ep->Line-ep->Topline)*Ysize);
  1068. }
  1069.  
  1070. extend(ep, lines)
  1071. register ED *ep;
  1072. {
  1073.     register long extra = ep->Maxlines - ep->Lines;
  1074.     register ubyte **list;
  1075.  
  1076.     if (lines > extra) {
  1077.     lines += ep->Lines;
  1078.     if (list = (ubyte **)allocl(lines)) {
  1079.         bmovl(ep->List, list, ep->Lines);
  1080.         FreeMem(ep->List, sizeof(char *) * ep->Maxlines);
  1081.         ep->Maxlines = lines;
  1082.         ep->List = list;
  1083.         return(1);
  1084.     }
  1085.     nomemory();
  1086.     return(0);
  1087.     }
  1088.     return(1);
  1089. }
  1090.  
  1091. makeroom(n)
  1092. {
  1093.     register ED *ep = Ep;
  1094.     if (ep->Lines >= ep->Maxlines)
  1095.     return(extend(ep, n));
  1096.     return(1);
  1097. }
  1098.  
  1099. freelist(list, n)
  1100. register char **list;
  1101. {
  1102.     while (n) {
  1103.     FreeMem(list[0], strlen(list[0])+1);
  1104.     ++list;
  1105.     --n;
  1106.     }
  1107. }
  1108.  
  1109.